package com.cq.hd.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cq.hd.common.pagination.Page;
import com.cq.hd.common.response.Throw;
import com.cq.hd.common.utils.BeanUtils;
import com.cq.hd.product.api.dto.LabelPageDto;
import com.cq.hd.product.api.dto.LabelSaveDto;
import com.cq.hd.product.api.vo.LabelPageVo;
import com.cq.hd.product.api.vo.LabelVo;
import com.cq.hd.product.mapper.TbLabelMapper;
import com.cq.hd.product.po.TbLabelPo;
import com.cq.hd.product.service.TbActiveLabelService;
import com.cq.hd.product.service.TbLabelService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author much
 * @since 2024/05/19 16:06
 */
@Service
public class TbLabelServiceImpl extends ServiceImpl<TbLabelMapper, TbLabelPo> implements TbLabelService {

    @Resource
    private TbLabelMapper labelMapper;
    @Resource
    private TbActiveLabelService activeLabelService;

    @Override
    public Page<LabelPageVo> pageLabel(LabelPageDto labelPageDto) {
        PageHelper.startPage(labelPageDto.getPageNum(), labelPageDto.getPageSize());
        List<LabelPageVo> dataList = labelMapper.selectLabelPage(labelPageDto);

        // 设置标签的引用数量
        List<Long> labelIds = dataList.stream().map(LabelPageVo::getId).collect(Collectors.toList());
        Map<Long, Integer> labelReferenceCounts = activeLabelService.getLabelReferenceCounts(labelIds);
        dataList.forEach(e -> {
            e.setReferenceCount(labelReferenceCounts.getOrDefault(e.getId(), 0));
        });

        PageInfo<LabelPageVo> pageInfo = new PageInfo<>(dataList);
        return Page.newPageWithAllFields(pageInfo.getList(), pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), pageInfo.getPages());
    }

    @Override
    public LabelVo saveLabel(LabelSaveDto labelSaveDto) {
        TbLabelPo tbLabelPo = BeanUtil.copyProperties(labelSaveDto, TbLabelPo.class);
        if (labelSaveDto.getId() == null) {
            tbLabelPo.setCreateTime(LocalDateTime.now());
            labelMapper.insert(tbLabelPo);
        } else {
            tbLabelPo.setUpdateTime(LocalDateTime.now());
            labelMapper.updateById(tbLabelPo);
        }
        return BeanUtil.copyProperties(tbLabelPo, LabelVo.class);
    }

    // 默认推荐商家最近添加的标签+随机后台标签，共10个（各一半，自建的不够后台的补足10个）
    @Override
    public List<LabelVo> listRecommendLabels(Long businessId) {
        // 平台标签
        List<TbLabelPo> platLabels = labelMapper.selectByBusinessId(0L);
        // 商家标签
        List<TbLabelPo> businessLabels = labelMapper.selectByBusinessId(businessId);

        List<LabelVo> resultList = new ArrayList<>();
        List<TbLabelPo> reversedBusinessLabels = businessLabels.stream()
                .sorted(Comparator.comparing(TbLabelPo::getCreateTime).reversed())
                .limit(5)
                .collect(Collectors.toList());

        resultList.addAll(reversedBusinessLabels.stream()
                .map(e -> BeanUtil.copyProperties(e, LabelVo.class))
                .collect(Collectors.toList())
        );
        resultList.addAll(randomLabels(platLabels, 10 - reversedBusinessLabels.size()));

        return resultList;
    }

    @Override
    public List<LabelVo> searchByClient(Long businessId, String keyword) {
        LambdaQueryWrapper<TbLabelPo> qw = Wrappers.<TbLabelPo>lambdaQuery()
                .in(TbLabelPo::getBusinessId, Arrays.asList(0L, businessId))
                .like(TbLabelPo::getName, keyword);
        return BeanUtils.copyListProperties(baseMapper.selectList(qw), LabelVo::new);
    }

    @Override
    public void deleteLabel(Long labelId) {
        Map<Long, Integer> labelReferenceCounts = activeLabelService.getLabelReferenceCounts(Collections.singletonList(labelId));
        if (labelReferenceCounts.getOrDefault(labelId, 0) > 0) {
            Throw.isBusinessException("当前标签已被活动引用，无法删除");
        }
        baseMapper.deleteById(labelId);
    }

    /**
     * 随机抽取num个标签
     *
     * @param labels 标签列表
     * @param randomNum 需要随机抽取的个数
     * @return
     */
    private List<LabelVo> randomLabels(List<TbLabelPo> labels, int randomNum) {
        if (CollectionUtils.isEmpty(labels)) {
            return Collections.emptyList();
        }

        Random random = new Random();
        // 计算要抽取的元素数量（最多 {randomNum} 个）
        int count = Math.min(randomNum, labels.size());
        // 生成所有的随机索引
        List<Integer> randomIndexes = random.ints(0, labels.size()).distinct().limit(count).boxed().collect(Collectors.toList());

        return randomIndexes.stream()
                .map(index -> BeanUtil.copyProperties(labels.get(index), LabelVo.class))
                .collect(Collectors.toList());
    }

}
